{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow IO Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qFdPvlXBOdUN"
      },
      "source": [
        "# 音声データの準備と拡張"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MfBg1C5NB3X0"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/io/tutorials/audio\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\"> TensorFlow.orgで表示</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\"> Google Colab で実行</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub でソースを表示{</a></td>\n",
        "      <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/io/tutorials/audio.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">ノートブックをダウンロード/a0}</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xHxb-dlhMIzW"
      },
      "source": [
        "## 概要\n",
        "\n",
        "自動音声認識における大きな課題の 1 つは、音声データの準備と拡張です。音声データ分析は、時間または周波数領域にあり可能性があるため、画像などのほかのデータソースと比べさらに複雑化します。\n",
        "\n",
        "TensorFlow エコシステムの一環として、`tensorflow-io` パッケージには、多数の有用な音声関連の API が提供されており、音声データの準備と拡張を単純化することができます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MUXex9ctTuDB"
      },
      "source": [
        "## セットアップ"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "upgCc3gXybsA"
      },
      "source": [
        "### 必要なパッケージをインストールし、ランタイムを再起動する"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uUDYyMZRfkX4"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow-io"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "J0ZKhA6s0Pjp"
      },
      "source": [
        "## 使用方法"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yZmI7l_GykcW"
      },
      "source": [
        "### 音声ファイルを読み取る\n",
        "\n",
        "TensorFlow IO では、クラス `tfio.audio.AudioIOTensor` を使用して、音声ファイルを遅延読み込みされる `IOTensor` に読み出すことができます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "nS3eTBvjt-O5"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_io as tfio\n",
        "\n",
        "audio = tfio.audio.AudioIOTensor('gs://cloud-samples-tests/speech/brooklyn.flac')\n",
        "\n",
        "print(audio)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z9GCyPWNuOm7"
      },
      "source": [
        "上記の例の Flac ファイル `brooklyn.flac` は、[google cloud](https://cloud.google.com/speech-to-text/docs/quickstart-gcloud) でパブリックアクセスが可能な音声クリップから得たものです。\n",
        "\n",
        "GCS は TensorFlow でサポートされているファイルシステムであるため、GCS アドレス `gs://cloud-samples-tests/speech/brooklyn.flac` が直接使用されています。`Flac` 形式のほか、`WAV`、`Ogg`、`MP3`、および `MP4A` 形式も `AudioIOTensor` の自動ファイル形式検出でサポートされています。\n",
        "\n",
        "`AudioIOTensor` は遅延読み込みされるため、最初は形状、dtype、およびサンプルレートしか表示されません。`AudioIOTensor` の形状は `[samples, channels]` で表現され、読み込んだ音声クリップが `int16` 型の `28979` サンプルを含む Mono チャンネルであることを示します。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IF_kYz_o2DH4"
      },
      "source": [
        "音声クリップのコンテンツは、`to_tensor()` 経由で `AudioIOTensor` から `Tensor` に変換するか、スライスによって、必要に応じてのみ読み取られます。スライスは、特に大きな音声クリップのほんの一部のみが必要である場合に役立ちます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "wtM_ixN724xb"
      },
      "outputs": [],
      "source": [
        "audio_slice = audio[100:]\n",
        "\n",
        "# remove last dimension\n",
        "audio_tensor = tf.squeeze(audio_slice, axis=[-1])\n",
        "\n",
        "print(audio_tensor)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IGnbXuVnSo8T"
      },
      "source": [
        "次のようにして、音声を再生できます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0rLbVxuFSvVO"
      },
      "outputs": [],
      "source": [
        "from IPython.display import Audio\n",
        "\n",
        "Audio(audio_tensor.numpy(), rate=audio.rate.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fmt4cn304IbG"
      },
      "source": [
        "テンソルを浮動小数点数に変換して音声クリップをグラフに表示するとより便利です。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZpwajOeR4UMU"
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "\n",
        "tensor = tf.cast(audio_tensor, tf.float32) / 32768.0\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(tensor.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "86qE8BPl5rcA"
      },
      "source": [
        "### ノイズをトリムする\n",
        "\n",
        "音声からノイズを取り除く方が好ましい場合があります。これは、API `tfio.experimental.audio.trim` を使用して行います。API から戻されるのは、セグメントの `[start, stop]` 位置のペアです。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "eEa0Z5U26Ep3"
      },
      "outputs": [],
      "source": [
        "position = tfio.experimental.audio.trim(tensor, axis=0, epsilon=0.1)\n",
        "print(position)\n",
        "\n",
        "start = position[0]\n",
        "stop = position[1]\n",
        "print(start, stop)\n",
        "\n",
        "processed = tensor[start:stop]\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(processed.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ineBzDeu-lTh"
      },
      "source": [
        "### フェードインとフェードアウト\n",
        "\n",
        "音声エンジニアリングの有用なテクニックには、フェードという、音声信号を徐々に増加または減少させるものがあります。これは、`tfio.experimental.audio.fade` を使用して行います。`tfio.experimental.audio.fade` は、`linear`、`logarithmic`、または `exponential` などのさまざまな形状のフェードをサポートしています。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LfZo0XaaAaeM"
      },
      "outputs": [],
      "source": [
        "fade = tfio.experimental.audio.fade(\n",
        "    processed, fade_in=1000, fade_out=2000, mode=\"logarithmic\")\n",
        "\n",
        "plt.figure()\n",
        "plt.plot(fade.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7rhLvOSZB0k0"
      },
      "source": [
        "### スペクトログラム\n",
        "\n",
        "多くの場合、高度な音声処理は、時間の経過に伴う周波数の変化に対応します。`tensorflow-io` では、`tfio.experimental.audio.spectrogram` を使って波形を変換することができます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UyFMBK-LDDnN"
      },
      "outputs": [],
      "source": [
        "# Convert to spectrogram\n",
        "spectrogram = tfio.experimental.audio.spectrogram(\n",
        "    fade, nfft=512, window=512, stride=256)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(tf.math.log(spectrogram).numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pZ92HnbJGHBS"
      },
      "source": [
        "異なるスケールへの追加の変換も可能です。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZgyedQdxGM2y"
      },
      "outputs": [],
      "source": [
        "# Convert to mel-spectrogram\n",
        "mel_spectrogram = tfio.experimental.audio.melscale(\n",
        "    spectrogram, rate=16000, mels=128, fmin=0, fmax=8000)\n",
        "\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(tf.math.log(mel_spectrogram).numpy())\n",
        "\n",
        "# Convert to db scale mel-spectrogram\n",
        "dbscale_mel_spectrogram = tfio.experimental.audio.dbscale(\n",
        "    mel_spectrogram, top_db=80)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(dbscale_mel_spectrogram.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nXd776xNIr_I"
      },
      "source": [
        "### SpecAugment\n",
        "\n",
        "上述したデータの準備と拡張 API のほか、`tensorflow-io` パッケージには、高度なスペクトログラムの拡張、特に [SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition（Park et al., 2019）](https://arxiv.org/pdf/1904.08779.pdf)で論じられている周波数と時間のマスキングも含まれています。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dajm7k-2J5l7"
      },
      "source": [
        "#### 周波数マスキング\n",
        "\n",
        "周波数マスキングでは、周波数チャンネルの `[f0, f0 + f)` がマスクされます。`f` は、`0` から周波数マスクパラメータ `F` までの一様分布から選択され、`f0` は、`(0, ν − f)` から選択されます。この `ν` は、周波数チャンネル数です。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kLEdfkkoK27A"
      },
      "outputs": [],
      "source": [
        "# Freq masking\n",
        "freq_mask = tfio.experimental.audio.freq_mask(dbscale_mel_spectrogram, param=10)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(freq_mask.numpy())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_luycpCWLe5l"
      },
      "source": [
        "#### 時間マスキング\n",
        "\n",
        "時間マスキングでは、`t` 個の連続した時間ステップ `[t0, t0 + t)` がマスクされます。`t` は、`0` から時間マスクパラメータ `T` までの一様分布から選択され、`t0` は、`[0, τ − t)` から選択されます。この `τ` は時間ステップ数です。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "G1ie8J3wMMEI"
      },
      "outputs": [],
      "source": [
        "# Time masking\n",
        "time_mask = tfio.experimental.audio.time_mask(dbscale_mel_spectrogram, param=10)\n",
        "\n",
        "plt.figure()\n",
        "plt.imshow(time_mask.numpy())"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [
        "Tce3stUlHN0L"
      ],
      "name": "audio.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
